home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / jmalloc.c < prev    next >
C/C++ Source or Header  |  1997-07-09  |  23KB  |  924 lines

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. //#include <new.h>
  5.  
  6. //#ifdef MEM_CHECK
  7. //#define MEM_CLEAR
  8. //#endif
  9.  
  10. #ifdef __WATCOMC__
  11. #include "doscall.hpp"
  12. #endif
  13. #include "jmalloc.hpp"
  14. #define uchar unsigned char
  15. #define JM_SMALL_SIZE 128      // above 128 bytes is considered to be a big block and no hashing is done
  16. int alloc_space=ALLOC_SPACE_STATIC;
  17.  
  18. extern void free_up_memory();
  19.  
  20. #ifdef MEM_CHECK
  21. long break_mem_point=0;       // can be set in debugger, break mem fun will be called when this address is allocated
  22. void break_mem_fun()
  23. {
  24.   printf("memory breakpoint\n");
  25. }
  26. #endif
  27.  
  28. struct memory_node
  29. {
  30.   long size;
  31. #ifdef MEM_CHECK
  32.   char *name;                     // name is allocated on regular heap
  33. #endif                            // because it is used for debugging purposes
  34.                                   // and will probably be run on my linux box with VMM
  35.   memory_node *next;
  36. };
  37.  
  38.  
  39. struct small_block
  40. {  
  41.   unsigned long size;                     // size of blocks...
  42.   unsigned long alloc_list;               // bit field saying weither each block is allocated or not.
  43.   small_block *next;                      // next small block of same size
  44. #ifdef MEM_CHECK
  45.   char *name[32];
  46. #endif 
  47. } ;
  48.  
  49. enum { HI_BLOCK, LOW_BLOCK }; 
  50.  
  51. class block_manager
  52. {
  53.   public :
  54.  
  55.   long block_size;                             // size of this memory_block
  56.   small_block *sblocks[JM_SMALL_SIZE];
  57.   small_block *cblocks[JM_SMALL_SIZE];
  58.   void *addr;
  59.  
  60.   memory_node *sfirst,*slast,
  61.               *cfirst;
  62.   unsigned char block_type;
  63.  
  64.   void init(void *block, long Block_size, uchar type);
  65.   void *static_alloc(long size, char *name);
  66.   void *cache_alloc(long size, char *name);
  67.   void static_free(void *ptr);
  68.   void cache_free(void *ptr);
  69.   long available();
  70.   long allocated();
  71.   long pointer_size(void *ptr);
  72.   void report(FILE *fp);
  73.   void inspect();
  74.  
  75.   int valid_static_ptr(void *ptr);     // only called from within debugger
  76.   int valid_cache_ptr(void *ptr);
  77. } bmanage[5];
  78.  
  79. int bmanage_total=0;
  80.  
  81.  
  82. void inspect_memory()
  83. {
  84.   for (int i=0;i<bmanage_total;i++)
  85.     bmanage[i].inspect();
  86. }
  87.  
  88.  
  89. int block_manager::valid_static_ptr(void *ptr)
  90. {
  91.   void *next=(void *)(*(((long *)ptr)-1));
  92.   if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
  93.   {
  94.     small_block *s=(small_block *)next;
  95.     if (s->size<=0) return 0;
  96.  
  97.     small_block *c=sblocks[s->size];
  98.     while (c && c!=s) c=c->next;
  99.     if (!c) return 0;
  100.   }
  101.  
  102.   memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
  103.   memory_node *f=sfirst;
  104.   while (f && f!=o) f=f->next;
  105.   if (f) return 1;
  106.   else return 0;
  107. }
  108.  
  109.  
  110. int block_manager::valid_cache_ptr(void *ptr)
  111. {
  112.   void *next=(void *)(*(((long *)ptr)-1));
  113.   if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
  114.   {
  115.     small_block *s=(small_block *)next;
  116.     if (s->size<=0) return 0;
  117.  
  118.     small_block *c=cblocks[s->size];
  119.     while (c && c!=s) c=c->next;
  120.     if (!c) return 0;
  121.   }
  122.  
  123.   memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
  124.   memory_node *f=cfirst;
  125.   while (f && f!=o) f=f->next;
  126.   if (f) return 1;
  127.   else return 0;
  128. }
  129.  
  130. void small_static_allocation_summary(int &total, int *&static_list, int *&cache_list)
  131. {
  132.   int size=1;
  133.   total=JM_SMALL_SIZE/4;
  134.   static_list=(int *)jmalloc(total*sizeof(int),"small static report");
  135.   cache_list=(int *)jmalloc(total*sizeof(int),"small cache report");
  136.   
  137.   for (;size<total;size++)
  138.   {
  139.     static_list[size]=0;
  140.     cache_list[size]=0;
  141.     int i,x;
  142.     for (i=0;i<bmanage_total;i++)
  143.     {
  144.       small_block *s=bmanage[i].sblocks[size];
  145.       while (s) 
  146.       { 
  147.                 for (x=0;x<32;x++)
  148.                   if (s->alloc_list&(1<<x))
  149.                     static_list[size]++; 
  150.             
  151.                 s=s->next; 
  152.       }
  153.  
  154.       s=bmanage[i].cblocks[size];
  155.       while (s) 
  156.       { 
  157.                 for (x=0;x<32;x++)
  158.                   if (s->alloc_list&(1<<x))
  159.                     cache_list[size]++; 
  160.             
  161.                 s=s->next; 
  162.       }
  163.     }
  164.   }
  165. }
  166.  
  167. void block_manager::inspect()
  168. {
  169.   memory_node *f=sfirst;
  170.   for (;f;f=f->next);               // scan through static big list
  171.  
  172.   int i,bit;
  173.   for (i=0;i<JM_SMALL_SIZE;i++)
  174.   {
  175.     for (small_block *s=sblocks[i];s;s=s->next)
  176.     {
  177.       char *addr=((char *)(s+1));
  178.       for (int j=0;j<32;j++)
  179.       {
  180.                 if (s->alloc_list&bit)
  181.                 {
  182.                   void *next=(void *)(*(((long *)addr)));
  183.                   if ((long)next!=(long)s)
  184.                   {
  185.                     fprintf(stderr,"inspect : bad pointer\n");
  186.                     return ;        
  187.                   }
  188.                 }
  189.                 bit=bit<<1;
  190.                 addr+=s->size+4;
  191.       }    
  192.     }
  193.   }
  194.  
  195. }
  196.  
  197. void block_manager::report(FILE *fp)
  198. {
  199.   fprintf(fp,"************** Block size = %d ***************\n",block_size);
  200.   fprintf(fp,"************** STATIC SPACE ******************\n");
  201.   int i=0;
  202.   memory_node *f=sfirst;
  203.   for (;f;f=f->next,i++)
  204.   {    
  205.     fprintf(fp,"%4d   %p (%d) %4d      ",i,f,((char *)f-(char *)sfirst),f->size);
  206. #ifdef MEM_CHECK
  207.     if (f->size>0)
  208.       fprintf(fp,"%s",f->name);
  209.     else fprintf(fp,"FREE");
  210. #endif
  211.     fprintf(fp,"\n");
  212.   }    
  213.   for (i=0;i<JM_SMALL_SIZE;i++)
  214.   {
  215.     for (small_block *s=sblocks[i];s;s=s->next)
  216.     {      
  217.       fprintf(fp,"*** Small Block size = %d ***\n",i);      
  218.       unsigned long x=0,bit=1;
  219.       char *addr=((char *)(s+1));
  220.       for (int j=0;j<32;j++)
  221.       {
  222.                 fprintf(fp,"%p   ",addr);
  223.                 if (s->alloc_list&bit)
  224.                 {
  225. #ifdef MEM_CHECK
  226.                   fprintf(fp,"%s\n",s->name[j]);
  227. #else
  228.                   fprintf(fp,"allocated\n");
  229. #endif      
  230.                 } else fprintf(fp,"FREE\n");
  231.                 bit=bit<<1;
  232.                 addr+=s->size+4;
  233.       }
  234.     }
  235.   }
  236.  
  237.  
  238.   fprintf(fp,"************** CACHE SPACE ******************\n",block_size);
  239.   i=0;
  240.   for (f=cfirst;f;f=f->next,i++)
  241.   {    
  242.     fprintf(fp,"%4d   %p %4d      ",i,f,f->size);
  243. #ifdef MEM_CHECK
  244.     if (f->size>0)
  245.       fprintf(fp,"%s",f->name);
  246.     else fprintf(fp,"FREE");
  247. #endif
  248.     fprintf(fp,"\n");
  249.   }    
  250.   for (i=0;i<JM_SMALL_SIZE;i++)
  251.   {
  252.     for (small_block *s=cblocks[i];s;s=s->next)
  253.     {      
  254.       fprintf(fp,"*** Small Block size = %d ***\n",i);      
  255.       unsigned long x=0,bit=1;
  256.       char *addr=((char *)(s+1));
  257.       for (int j=0;j<32;j++)
  258.       {
  259.     fprintf(fp,"%p   ",addr);
  260.     if (s->alloc_list&bit)
  261.     {
  262. #ifdef MEM_CHECK
  263.       fprintf(fp,"%s\n",s->name[j]);
  264. #else
  265.       fprintf(fp,"allocated\n");
  266. #endif      
  267.     } else fprintf(fp,"FREE\n");
  268.     bit=bit<<1;
  269.     addr+=s->size+4;
  270.       }
  271.     }
  272.   }
  273. }
  274.  
  275. long block_manager::pointer_size(void *ptr)
  276. {
  277.   void *next=(void *)(*(((long *)ptr)-1));
  278.   if (next>ptr)
  279.     return ((memory_node *)(((char *)ptr)-sizeof(memory_node)))->size;
  280.   else return ((small_block *)next)->size;
  281. }
  282.  
  283. long block_manager::available()
  284. {
  285.   long size=0;
  286.   memory_node *f;
  287.   for (f=sfirst;f;f=f->next)
  288.     if (f->size<0) size-=f->size;
  289.  
  290.   for (f=cfirst;f;f=f->next)
  291.     if (f->size<0) size-=f->size;
  292.   return size;
  293. }
  294.  
  295. long block_manager::allocated()
  296. {
  297.   long size=0;
  298.   memory_node *f;
  299.   for (f=sfirst;f;f=f->next)
  300.     if (f->size>0) size+=f->size;
  301.  
  302.   for (f=cfirst;f;f=f->next)
  303.     if (f->size>0) size+=f->size;
  304.   return size;
  305. }
  306.  
  307. void block_manager::init(void *block, long Block_size, uchar type)
  308. {
  309.   block_size=Block_size;
  310.   addr=block;
  311.   /* 
  312.      I'm padding each block, because I'm comparing pointers against size
  313.      in jfree to determine weither a pointer is too a small object or a large alloc
  314.      and it must always be true that the address of the pointer is > JM_SMALL_SIZE 
  315.      All systems I know start pointer address pretty high, but this is a porting consern.     
  316.   */
  317.   
  318.   slast=sfirst=(memory_node *)(((char *)block)+JM_SMALL_SIZE);   
  319.   sfirst->size=-(block_size-sizeof(memory_node)-JM_SMALL_SIZE);
  320.   sfirst->next=NULL;
  321.   cfirst=NULL;
  322.   memset(sblocks,0,sizeof(sblocks));
  323.   memset(cblocks,0,sizeof(cblocks));
  324.   block_type=type;
  325. }
  326.  
  327. void *block_manager::static_alloc(long size, char *name)
  328. {
  329.   if (size<JM_SMALL_SIZE)
  330.   {
  331.     small_block *s=sblocks[size];
  332.     for (;s && s->alloc_list==0xffffffff;s=s->next);
  333.     if (!s)
  334.     {
  335.       s=(small_block *)static_alloc((size+4)*32+sizeof(small_block),"small_block");
  336.       if (!s) return NULL;   // not enough room for another small block
  337.       s->alloc_list=1;
  338.       s->next=sblocks[size];
  339.       sblocks[size]=s;
  340.       s->size=size;
  341. #ifdef MEM_CHECK
  342.       s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
  343.       if ((long)s==break_mem_point)
  344.         break_mem_fun();
  345. #endif      
  346.       long *addr=(long *)(((char *)s)+sizeof(small_block));
  347.       *addr=(long)s;
  348.       return (void *)(addr+1);  // return first block
  349.     } else
  350.     {
  351.       int bit=1,i=0,offset=0;
  352.       char *addr=((char *)s)+sizeof(small_block);
  353.       while (1)        // we already know there is a bit free
  354.       {
  355.     if ((s->alloc_list&bit)==0)
  356.     {
  357.       s->alloc_list|=bit;
  358. #ifdef MEM_CHECK
  359.       s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
  360. #endif           
  361.       *((long *)addr)=(long)s;
  362.  
  363. #ifdef MEM_CHECK
  364.       if ((long)addr==break_mem_point)
  365.             break_mem_fun();
  366. #endif
  367.  
  368.       return (void *)(addr+4);
  369.     }
  370.     i++;
  371.     bit=bit<<1;
  372.     addr+=size+4;
  373.       }      
  374.     }                
  375.   }
  376.  
  377.  
  378.   memory_node *s=sfirst;
  379.   for (;s && -s->size<size;s=s->next);
  380.   if (!s) return NULL;
  381.   s->size=-s->size;
  382.  
  383.   if (s->size-size>sizeof(memory_node)+4)  // is there enough space to split the block?
  384.   {    
  385.     memory_node *p=(memory_node *)((char *)s+sizeof(memory_node)+size);
  386.     if (s==slast)
  387.       slast=p;
  388.     p->size=-(s->size-size-sizeof(memory_node));
  389. #ifdef MEM_CLEAR
  390. //    memset( ((memory_node *)p)+1,0,-p->size);
  391. #endif
  392.     p->next=s->next;
  393.     s->next=p;
  394.     s->size=size;
  395.   }
  396. #ifdef MEM_CHECK
  397.   s->name=strcpy((char *)malloc(strlen(name)+1),name);
  398.  
  399.   if ((long)s==break_mem_point)
  400.     break_mem_fun();
  401.  
  402. #endif
  403.   return (void *)(((char *)s)+sizeof(memory_node));
  404. }
  405.  
  406.  
  407. void *block_manager::cache_alloc(long size, char *name)
  408. {
  409.   if (size<JM_SMALL_SIZE)
  410.   {
  411.     small_block *s=cblocks[size];
  412.     for (;s && s->alloc_list==0xffffffff;s=s->next);
  413.     if (!s)
  414.     {
  415.       s=(small_block *)cache_alloc((size+4)*32+sizeof(small_block),"small_block");
  416.       if (!s) return NULL;   // not enough room for another small block
  417.       s->alloc_list=1;
  418.       s->next=cblocks[size];
  419.       cblocks[size]=s;
  420.       s->size=size;
  421. #ifdef MEM_CHECK
  422.       s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
  423.  
  424. #endif      
  425.       long *addr=(long *)(((char *)s)+sizeof(small_block));
  426.       *addr=(long)s;
  427. #ifdef MEM_CHECK
  428.       if ((long)s==break_mem_point)
  429.         break_mem_fun();
  430. #endif
  431.       return (void *)(addr+1);  // return first block
  432.     } else
  433.     {
  434.       int bit=1,i=0,offset=0;
  435.       char *addr=((char *)s)+sizeof(small_block);
  436.       while (1)        // we already know there is a bit free
  437.       {
  438.     if ((s->alloc_list&bit)==0)
  439.     {
  440.       s->alloc_list|=bit;
  441. #ifdef MEM_CHECK
  442.       s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
  443.       if ((long)s==break_mem_point)
  444.         break_mem_fun();
  445. #endif           
  446.       *((long *)addr)=(long)s;
  447.       return (void *)(addr+4);
  448.     }
  449.     i++;
  450.     bit=bit<<1;
  451.     addr+=size+4;
  452.       }      
  453.     }                
  454.   }
  455.  
  456.  
  457.   memory_node *clast=NULL;
  458.   memory_node *s=cfirst;
  459.   for (;s && -s->size<size;s=s->next) clast=s;
  460.   if (!s) // no current cache space for object, see if we can enlarge the cache space
  461.   {
  462.     long size_avail=-slast->size;
  463.     size_avail-=sizeof(memory_node);
  464.  
  465.     if (slast->size>0 || size_avail<size) // not enough space
  466.       return NULL;
  467.     else
  468.     {
  469.       slast->size+=size+sizeof(memory_node);
  470.       memory_node *nc=(memory_node *)(((char *)(slast)) + (-slast->size+sizeof(memory_node)));
  471.       
  472.       nc->next=NULL;
  473.       nc->size=size;
  474. #ifdef MEM_CHECK
  475.       nc->name=strcpy((char *)malloc(strlen(name)+1),name);      
  476.       if ((long)nc==break_mem_point)
  477.         break_mem_fun();
  478. #endif      
  479.       if (!clast)
  480.         cfirst=nc;
  481.       else clast->next=nc;
  482.       return (void *)(((char *)nc)+sizeof(memory_node));
  483.     }
  484.   }
  485.  
  486.  
  487.   s->size=-s->size;
  488.  
  489.   if (s->size-size>sizeof(memory_node)+4)  // is there enough space to split the block?
  490.   {
  491.     memory_node *p=s;    // store this position
  492.     long psize=s->size-size-sizeof(memory_node);
  493.     s=(memory_node *)(((char *)s)+psize+sizeof(memory_node));
  494.     p->size=-psize;
  495.     s->next=p;
  496.     s->size=size;
  497.     if (cfirst==p) cfirst=s;
  498.     else clast->next=s;
  499.   }
  500. #ifdef MEM_CHECK
  501.   s->name=strcpy((char *)malloc(strlen(name)+1),name);
  502.   if ((long)s==break_mem_point)
  503.     break_mem_fun();
  504. #endif
  505.   return (void *)(((char *)s)+sizeof(memory_node));
  506. }
  507.  
  508.  
  509. /************************** CACHE FREE ****************************/
  510. /*    should be called to free a pointer in the cache heap        */
  511. /*    i.e. end of the heap                                        */
  512. /******************************************************************/
  513. void block_manager::cache_free(void *ptr)
  514. {
  515.   // see if this was a small_block allocation
  516.   void *next=(void *)(*(((long *)ptr)-1));
  517.   if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
  518.   {
  519.     small_block *s=(small_block *)next;
  520.     if (s->size<=0)
  521.     {
  522.       fprintf(stderr,"jfree : bad pointer\n");
  523.       return ;
  524.     }
  525.  
  526.     int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
  527. #ifdef MEM_CHECK
  528.     free(s->name[field]);
  529. #endif
  530.     s->alloc_list&=(0xffffffff-(1<<field));
  531.     if (s->alloc_list==0)
  532.     {
  533.       small_block *l=NULL;
  534.       small_block *n=cblocks[s->size];
  535.       for (;n!=s;n=n->next) l=n;
  536. #ifdef MEM_CHECK
  537.       if (!n) 
  538.       { printf("Free small block error\n"); }
  539. #endif
  540.       if (!l)
  541.       cblocks[s->size]=s->next;
  542.       else l->next=s->next;
  543.       cache_free(s);
  544.     }      
  545.   } else
  546.   {
  547.     memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
  548.     memory_node *n=cfirst;
  549.     for (;n && n!=o;n=n->next) last=n;
  550. #ifdef MEM_CHECK
  551.     if (!n) 
  552.     { printf("Free cached big block error\n"); }
  553.     free(o->name);
  554. #endif
  555.     
  556.     if (last && last->size<0)   // can we add into last block
  557.     {
  558.       memory_node *prev=NULL;
  559.       for (memory_node *n=cfirst;n && n!=last;n=n->next) prev=n;   // find previous to last pointer
  560.       if (prev)
  561.         prev->next=o;
  562.       else cfirst=o;
  563.  
  564.       o->size=last->size-o->size-sizeof(memory_node);
  565.       last=prev;
  566.     } else o->size=-o->size;
  567.     
  568.     if (!o->next)           // if no next block, then we should add back into static memory
  569.     {
  570.       if (last) last->next=NULL;  // unlink from cache chain
  571.       else cfirst=NULL;
  572.  
  573.       if (slast->size>0)    // if last static is allocated then create a new free static at end of list
  574.       {
  575.     slast->next=o;
  576.     slast=o;
  577.       } else      
  578.     slast->size+=o->size-sizeof(memory_node);  // else just increase the size of last block
  579.     } else if (o->next->size<0)   // see if we can add into next block
  580.     {
  581.       o->next->size+=o->size-sizeof(memory_node);
  582.       if (last)      
  583.     last->next=o->next;
  584.       else
  585.         cfirst=o->next;
  586.     }
  587.   }  
  588. }
  589.  
  590.  
  591.  
  592. /************************** STATIC FREE ***************************/
  593. /*    should be called to free a pointer in the static heap       */
  594. /*    i.e. begining of the heap                                   */
  595. /******************************************************************/
  596. void block_manager::static_free(void *ptr)
  597. {
  598.   // see if this was a small_block allocation
  599.   void *next=(void *)(*(((long *)ptr)-1));
  600.   if (next && next<ptr)  // small allocation
  601.   {
  602.     small_block *s=(small_block *)next;
  603.     if (s->size<=0)
  604.     {
  605.       fprintf(stderr,"jfree : bad pointer\n");
  606.       return ;
  607.     }
  608. #ifdef MEM_CLEAR
  609.     memset(ptr,0,s->size);
  610. #endif
  611.  
  612.     int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
  613. #ifdef MEM_CHECK
  614.     free(s->name[field]);
  615. #endif
  616.     s->alloc_list&=(0xffffffff-(1<<field));
  617.     if (s->alloc_list==0)
  618.     {
  619.       small_block *l=NULL;
  620.       small_block *n=sblocks[s->size];
  621.       for (;n!=s;n=n->next) l=n;
  622. #ifdef MEM_CHECK
  623.       if (!n) { printf("Free static small block error\n"); }
  624. #endif
  625.       if (!l)
  626.       sblocks[s->size]=s->next;
  627.       else l->next=s->next;
  628.       static_free(s);
  629.     }      
  630.   } else
  631.   {
  632.     memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
  633. #ifdef MEM_CHECK
  634.     free(o->name);
  635. #endif
  636. #ifdef MEM_CLEAR
  637.     memset(ptr,0,o->size);
  638. #endif
  639.  
  640.     if (o->next && o->next->size<0)   // see if we can add into next block
  641.     {
  642.       if (o->next==slast)
  643.         slast=o;
  644.       o->size+=-o->next->size+sizeof(memory_node);
  645.       o->next=o->next->next;
  646.     }
  647.  
  648.     memory_node *n=sfirst;
  649.     for (;n && n!=o;n=n->next) last=n;
  650. #ifdef MEM_CHECK
  651.     if (!n) { printf("Free static big block error\n"); }
  652. #endif
  653.     
  654.     if (last && last->size<0)
  655.     {
  656.       if (o==slast) slast=last;
  657.       last->next=o->next;
  658.       last->size-=o->size+sizeof(memory_node);    
  659.     } else o->size=-o->size;            
  660.   }  
  661. }
  662.  
  663.  
  664. void jmalloc_uninit()
  665. {
  666.   for (int i=0;i<bmanage_total;i++)
  667.   {
  668.     switch (bmanage[i].block_type)
  669.     {
  670.       case HI_BLOCK : 
  671.       { free(bmanage[i].addr); } break;
  672. #ifdef __WATCOMC__      
  673.       case LOW_BLOCK :
  674.       { free_low_memory(bmanage[i].addr); } break;
  675. #endif      
  676.     }
  677.   }
  678.   bmanage_total=0;
  679. }
  680.  
  681. void jmem_cleanup(int ret, void *arg)
  682. { jmalloc_uninit(); }
  683.  
  684.  
  685. int jmalloc_max_size=3072000;
  686. int jmalloc_min_low_size=0x1000;
  687. char *not_enough_total_memory_message="Memory manager : Sorry you do not have enough memory available to\n"
  688.                                        "                 run this program.\n"
  689.                        "    DOS users  : Remove any TSR's and device drivers you can.\n"
  690.                        "    UNIX users : Do you have a swapfile/partition setup?\n";
  691. char *not_enough_low_memory_message="Memory Manager : Not enough low memory available (%d : need %d)\n"
  692.                                    "  Suggestions...\n"
  693.                    "    - make a boot disk\n"
  694.                    "    - remove TSR's  & drivers not needed by ABUSE\n"
  695.                    "    - add memory to your system\n";
  696.  
  697. void jmalloc_init(long min_size)
  698. {
  699.   if (bmanage_total)
  700.     fprintf(stderr,"warning : jmalloc_init called twice\n");
  701.   else
  702.   {
  703. //    exit_proc(jmem_cleanup,jmalloc_uninit);          // make sure memory gets freed up on exit
  704.     void *mem;
  705.  
  706. #ifdef __POWERPC__
  707.     long size=jmalloc_max_size-0x10000;
  708.     for (mem=NULL;!mem && size>0x10000;)
  709.     {
  710.       mem=malloc(size+0x10000);
  711.       if (!mem) size-=0x100;        
  712.     }
  713.     free(mem);
  714.     mem = malloc(size);
  715. #else
  716.     long size=jmalloc_max_size;
  717.     for (mem=NULL;!mem && size>0x4000;)
  718.     {
  719.       mem=malloc(size);
  720.       if (!mem) size-=0x100;        
  721.     }
  722. #endif
  723.     if (mem)
  724.     {
  725.             bmanage[bmanage_total].init(mem,size,HI_BLOCK);
  726.             bmanage_total++;      
  727.             fprintf(stderr,"Added himem block (%d bytes)\n",size);
  728.     }
  729.  
  730. /*    bmanage[bmanage_total].init(malloc(2039552),2039552,HI_BLOCK);
  731.     bmanage_total++;      
  732.     bmanage[bmanage_total].init(malloc(150224),150224,HI_BLOCK);
  733.     bmanage_total++;      */
  734.  
  735.  
  736.  
  737. #ifdef __WATCOMC__
  738.     if (size!=jmalloc_max_size)
  739.     {
  740.       do
  741.       {
  742.                 size=low_memory_available();
  743.                 if (size>jmalloc_min_low_size+0x1000)              // save 64K for misc low memory needs
  744.                 {
  745.                   bmanage[bmanage_total].init(alloc_low_memory(size-jmalloc_min_low_size-0x1000),size-jmalloc_min_low_size-0x1000,LOW_BLOCK);
  746.                   bmanage_total++; 
  747.                   fprintf(stderr,"Added low memory block (%d bytes)\n",size);
  748.                 }
  749.       } while (size>jmalloc_min_low_size+0x1000);
  750.       if (size<jmalloc_min_low_size)
  751.       {
  752.                 fprintf(stderr,not_enough_low_memory_message,size,jmalloc_min_low_size);
  753.                 exit(0);
  754.       }
  755.     }
  756. #endif
  757.  
  758.  
  759.     fprintf(stderr,"Memory available : %d\n",j_available());
  760.     if (j_available()<min_size)
  761.     {
  762.       fprintf(stderr,not_enough_total_memory_message);
  763.       exit(0);
  764.     }
  765.  
  766.   }
  767. }
  768.  
  769.  
  770. long j_available()
  771. {
  772.   long size=0;
  773.   for (int i=0;i<bmanage_total;i++) 
  774.     size+=bmanage[i].available();
  775.   return size;
  776. }
  777.  
  778. long j_allocated()
  779. {
  780.   long size=0;
  781.   for (int i=0;i<bmanage_total;i++) 
  782.     size+=bmanage[i].allocated();
  783.   return size;
  784. }
  785.  
  786.  
  787. void *jmalloc(long size, char *name)
  788. {  
  789.   if (!bmanage_total)
  790.     return malloc(size);
  791.  
  792.   size=(size+3)&(0xffffffff-3);
  793.   do
  794.   {
  795.     for (int i=0;i<bmanage_total;i++)
  796.     {
  797.       void *a;
  798.       if (alloc_space==ALLOC_SPACE_STATIC)
  799.         a=bmanage[i].static_alloc(size,name);
  800.       else
  801.         a=bmanage[i].cache_alloc(size,name);
  802.       if (a) return a;
  803.     }
  804.     free_up_memory();
  805.   } while (1);  
  806. }
  807.  
  808. void jfree(void *ptr)
  809. {
  810.   if (ptr == NULL)
  811.     return;
  812.   if (!bmanage_total) 
  813.   { 
  814.     free(ptr); 
  815.     return ; 
  816.   }
  817.   for (int i=0;i<bmanage_total;i++)
  818.     if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
  819.     {
  820.       if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
  821.       {
  822.     bmanage[i].static_free(ptr);
  823.     return ;
  824.       } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
  825.       {
  826.     bmanage[i].cache_free(ptr);
  827.     return ;
  828.       }
  829.     }
  830.  
  831.   free (ptr);  
  832. //  fprintf(stderr,"jfree : bad pointer\n");
  833. }
  834.  
  835.  
  836. void *jrealloc(void *ptr, long size, char *name)
  837. {  
  838.   if (!ptr) return jmalloc(size,name);
  839.   if (!bmanage_total) { return realloc(ptr,size); }
  840.  
  841.   if (size==0) { jfree(ptr); return NULL; }
  842.  
  843.   long old_size=0;
  844.   for (int i=0;i<bmanage_total;i++)
  845.     if (ptr>=(void *)bmanage[i].sfirst && 
  846.     ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))
  847.     {
  848.       old_size=bmanage[i].pointer_size(ptr);  
  849.       if (ptr<=(void *)bmanage[i].slast)
  850.       {
  851.     int sp=alloc_space; sp=ALLOC_SPACE_STATIC;
  852.     void *nptr=jmalloc(size,name);
  853.     if (size>old_size)
  854.       memcpy(nptr,ptr,old_size);
  855.      else memcpy(nptr,ptr,size);
  856.     bmanage[i].static_free(ptr);
  857.     alloc_space=sp;
  858.     return nptr;
  859.       } else
  860.       {
  861.     int sp=alloc_space; sp=ALLOC_SPACE_CACHE;
  862.     void *nptr=jmalloc(size,name);
  863.     if (size>old_size)
  864.       memcpy(nptr,ptr,old_size);
  865.     else memcpy(nptr,ptr,size);
  866.     bmanage[i].cache_free(ptr);
  867.     alloc_space=sp;
  868.     return nptr;
  869.       }
  870.     }
  871.   fprintf(stderr,"jrealloc : bad pointer\n");
  872.   return NULL;
  873. }
  874.  
  875. void dmem_report()
  876. {
  877.   mem_report("debug.mem");
  878. }
  879.  
  880.  
  881. void mem_report(char *filename)
  882. {
  883.   FILE *fp=fopen(filename,"wb");
  884.   for (int i=0;i<bmanage_total;i++)
  885.     bmanage[i].report(fp);
  886.   fclose(fp);
  887. }
  888.  
  889. void *operator new( size_t size)
  890. {  
  891.   return jmalloc(size,"::new object");
  892.  
  893. void operator delete(void *ptr)
  894. {
  895.   jfree(ptr);
  896. }
  897.  
  898.  
  899. long small_ptr_size(void *ptr)
  900. {
  901.   return ((small_block *)(((long *)ptr)[-1]))->size;
  902. }
  903.  
  904.  
  905. int valid_ptr(void *ptr)
  906. {
  907.   if (!bmanage_total) { return 0; }
  908.   for (int i=0;i<bmanage_total;i++)
  909.     if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
  910.     {
  911.       if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
  912.       {
  913.     return bmanage[i].valid_static_ptr(ptr);
  914.       } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
  915.       {
  916.     return bmanage[i].valid_cache_ptr(ptr);
  917.       }
  918.     }
  919.  
  920.   return 0;
  921. }
  922.  
  923.